package com.buka.recipe.security.filter;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.buka.recipe.security.token.WechatAuthenticationToken;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.io.IOException;
import java.io.InputStream;

@Log4j2
public class WechatAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    // 设置拦截/device/login设备登录接口
    private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/wechat/login", "POST");

    public WechatAuthenticationFilter() {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (!"POST".equalsIgnoreCase(request.getMethod())) {
            throw new AuthenticationServiceException("Device authentication method not supported: " + request.getMethod());
        }
        // 获取请求头，据此判断请求参数类型
        if (!request.getContentType().startsWith(MediaType.APPLICATION_JSON_VALUE)) {
            throw new AuthenticationServiceException("Device authentication method not supported: " + request.getMethod() + ", need json.");
        }

        WechatAuthenticationToken authRequest = null;
        try (InputStream is = request.getInputStream()) {
            JSONObject authenticationJson = JSON.parseObject(is);
            // 认证参数
            String code = authenticationJson.getString("code");
            log.debug("login code : {}", code);
            authRequest = WechatAuthenticationToken.unauthenticated(code);
            setDetails(request, authRequest);
        } catch (IOException e) {
            log.error("解析用户登录参数错误, {}", e.getMessage());
        }
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    protected void setDetails(HttpServletRequest request, WechatAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

}
